import { AppInitError } from "@/models/errors";

const m_tableNamePat = /(?:from|join)\s+(\w+\b)/igm
const m_fieldsForHeaderPat = /(?:select)\s+?(.+?)\s+from/ims

export type TSqlAnalyzeService = ReturnType<typeof getServices>

export function getServices() {


    function getTableNames(sql: string): string[] {

        const tableNames = Array.from(sql.matchAll(m_tableNamePat))
        if (tableNames.length === 0) {
            throw new AppInitError(`table name not found in [${sql}]`, '如果表名包含{},你可能忘记使用 python 的 f-string');
        }

        return tableNames.map(v => v[1])
    }

    function getFieldsForHeader(sql: string) {

        const fieldsPart = sql.match(m_fieldsForHeaderPat)
        if (fieldsPart === null) {
            throw new AppInitError(`fields not found in [${sql}]`);
        }

        const names = []

        for (const name of iterName(fieldsPart[1])) {
            const arr = name.split(' as ')
            if (arr.length === 1) {
                names.push(name.trim())
            } else {
                names.push(arr[1].trim())
            }
        }

        return names

    }

    function replaceTableToFilterQuery(sql: string, tableName: string, querySql: string) {

        return sql.replace(new RegExp(`${m_ReplaceTableRegPat.pat}${tableName}`, m_ReplaceTableRegPat.flags), `$1 (${querySql})`)
    }

    return {
        getTableNames: getTableNames,
        getFieldsForHeader,
        replaceTableToFilterQuery,
    }
}

function* iterName(text: string) {
    let bracketsNum = 0
    let startIdx = 0

    for (let curIdx = 0; curIdx < text.length; curIdx++) {
        const letter = text[curIdx];
        if (letter == "," && bracketsNum == 0) {
            yield text.slice(startIdx, curIdx)
            startIdx = curIdx + 1
        } else if (letter == "(") {
            bracketsNum += 1
        } else if (letter == ")") {
            bracketsNum -= 1
        }
    }

    if (startIdx <= text.length - 1) {
        yield text.slice(startIdx, text.length)
    }

}



function buildReplaceTableToFilterQuery() {
    const leftJoin = `left\\s*?(outer)?\\s*?join`
    const rightJoin = `right\\s*?(outer)?\\s*?join`
    const innerJoin = `(inner)?\\s*?join`
    const crossJoin = `cross\\s*?join`
    const from = `from`
    const res = `(${from}|${leftJoin}|${rightJoin}|${innerJoin}|${crossJoin})\\s+?`
    return {
        pat: res,
        flags: 'gim'
    }
}

const m_ReplaceTableRegPat = buildReplaceTableToFilterQuery()


